home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / stream_output / stream_output.c
C/C++ Source or Header  |  2003-04-07  |  36KB  |  1,303 lines

  1. /*****************************************************************************
  2.  * stream_output.c : stream output module
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: stream_output.c,v 1.23 2003/03/31 03:46:11 fenrir Exp $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Laurent Aimar <fenrir@via.ecp.fr>
  9.  *          Eric Petit <titer@videolan.org>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25.  
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #include <stdlib.h>                                                /* free() */
  30. #include <stdio.h>                                              /* sprintf() */
  31. #include <string.h>                                            /* strerror() */
  32.  
  33. #include <vlc/vlc.h>
  34.  
  35. #include <vlc/sout.h>
  36. #undef DEBUG_BUFFER
  37. /*****************************************************************************
  38.  * Local prototypes
  39.  *****************************************************************************/
  40. static int          InstanceNewOutput   ( sout_instance_t *, char * );
  41. static int          InstanceMuxNew      ( sout_instance_t *,
  42.                                           char *, char *, char * );
  43.  
  44. static sout_mux_t * MuxNew              ( sout_instance_t*,
  45.                                           char *, sout_access_out_t * );
  46. static sout_input_t *MuxAddStream       ( sout_mux_t *, sout_packet_format_t * );
  47. static void         MuxDeleteStream     ( sout_mux_t *, sout_input_t * );
  48. static void         MuxDelete           ( sout_mux_t * );
  49.  
  50. #if 0
  51. typedef struct
  52. {
  53.     /* if muxer doesn't support adding stream at any time then we first wait
  54.      *  for stream then we refuse all stream and start muxing */
  55.     vlc_bool_t  b_add_stream_any_time;
  56.     vlc_bool_t  b_waiting_stream;
  57.  
  58.     /* we wait one second after first stream added */
  59.     mtime_t     i_add_stream_start;
  60.  
  61. } sout_instance_sys_mux_t;
  62. #endif
  63.  
  64. struct sout_instance_sys_t
  65. {
  66.     int i_d_u_m_m_y;
  67. };
  68.  
  69. /*
  70.  * Generic MRL parser
  71.  *
  72.  */
  73. /* <access>{options}/<way>{options}://<name> */
  74. typedef struct mrl_option_s
  75. {
  76.     struct mrl_option_s *p_next;
  77.  
  78.     char *psz_name;
  79.     char *psz_value;
  80. } mrl_option_t;
  81.  
  82. typedef struct
  83. {
  84.     char            *psz_access;
  85.     mrl_option_t    *p_access_options;
  86.  
  87.     char            *psz_way;
  88.     mrl_option_t    *p_way_options;
  89.  
  90.     char *psz_name;
  91. } mrl_t;
  92.  
  93. /* mrl_Parse: parse psz_mrl and fill p_mrl */
  94. static int  mrl_Parse( mrl_t *p_mrl, char *psz_mrl );
  95. /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
  96. static void mrl_Clean( mrl_t *p_mrl );
  97.  
  98. /* some macro */
  99. #define TAB_APPEND( count, tab, p )             \
  100.     if( (count) > 0 )                           \
  101.     {                                           \
  102.         (tab) = realloc( (tab), sizeof( void ** ) * ( (count) + 1 ) ); \
  103.     }                                           \
  104.     else                                        \
  105.     {                                           \
  106.         (tab) = malloc( sizeof( void ** ) );    \
  107.     }                                           \
  108.     (void**)(tab)[(count)] = (void*)(p);        \
  109.     (count)++
  110.  
  111. #define TAB_FIND( count, tab, p, index )        \
  112.     {                                           \
  113.         int _i_;                                \
  114.         (index) = -1;                           \
  115.         for( _i_ = 0; _i_ < (count); _i_++ )    \
  116.         {                                       \
  117.             if((void**)(tab)[_i_]==(void*)(p))  \
  118.             {                                   \
  119.                 (index) = _i_;                  \
  120.                 break;                          \
  121.             }                                   \
  122.         }                                       \
  123.     }
  124.  
  125. #define TAB_REMOVE( count, tab, p )             \
  126.     {                                           \
  127.         int i_index;                            \
  128.         TAB_FIND( count, tab, p, i_index );     \
  129.         if( i_index >= 0 )                      \
  130.         {                                       \
  131.             if( count > 1 )                     \
  132.             {                                   \
  133.                 memmove( ((void**)tab + i_index),    \
  134.                          ((void**)tab + i_index+1),  \
  135.                          ( (count) - i_index - 1 ) * sizeof( void* ) );\
  136.             }                                   \
  137.             else                                \
  138.             {                                   \
  139.                 free( tab );                    \
  140.                 (tab) = NULL;                   \
  141.             }                                   \
  142.             (count)--;                          \
  143.         }                                       \
  144.     }
  145.  
  146. #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
  147.  
  148. /*****************************************************************************
  149.  * sout_NewInstance: creates a new stream output instance
  150.  *****************************************************************************/
  151. sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
  152.                                        char * psz_dest )
  153. {
  154.     sout_instance_t *p_sout;
  155.     char            *psz_dup, *psz_parser, *psz_pos;
  156.  
  157.     /* Allocate descriptor */
  158.     p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
  159.     if( p_sout == NULL )
  160.     {
  161.         msg_Err( p_parent, "out of memory" );
  162.         return NULL;
  163.     }
  164.  
  165.     p_sout->psz_sout    = NULL;
  166.  
  167.     p_sout->i_nb_dest   = 0;
  168.     p_sout->ppsz_dest   = NULL;
  169.  
  170.     p_sout->i_preheader = 0;
  171.     p_sout->i_nb_mux    = 0;
  172.     p_sout->pp_mux      = 0;
  173.  
  174.     vlc_mutex_init( p_sout, &p_sout->lock );
  175.     p_sout->i_nb_inputs = 0;
  176.     p_sout->pp_inputs   = NULL;
  177.  
  178.     p_sout->p_sys           = malloc( sizeof( sout_instance_sys_t ) );
  179.  
  180.     /* now parse psz_sout */
  181.     psz_dup = strdup( psz_dest );
  182.     psz_parser = psz_dup;
  183.  
  184.     while( ( psz_pos = strchr( psz_parser, '#' ) ) != NULL )
  185.     {
  186.         *psz_pos++ = '\0';
  187.  
  188.         if( InstanceNewOutput( p_sout, psz_parser ) )
  189.         {
  190.             msg_Err( p_sout, "adding `%s' failed", psz_parser );
  191.         }
  192.  
  193.         psz_parser = psz_pos;
  194.     }
  195.  
  196.     if( *psz_parser )
  197.     {
  198.         if( InstanceNewOutput( p_sout, psz_parser ) )
  199.         {
  200.             msg_Err( p_sout, "adding `%s' failed", psz_parser );
  201.         }
  202.     }
  203.  
  204.     free( psz_dup );
  205.  
  206.     if( p_sout->i_nb_dest <= 0 )
  207.     {
  208.         msg_Err( p_sout, "all sout failed" );
  209.         vlc_object_destroy( p_sout );
  210.         return( NULL );
  211.     }
  212.  
  213.     vlc_object_attach( p_sout, p_parent );
  214.  
  215.     return p_sout;
  216. }
  217. /*****************************************************************************
  218.  * sout_DeleteInstance: delete a previously allocated instance
  219.  *****************************************************************************/
  220. void sout_DeleteInstance( sout_instance_t * p_sout )
  221. {
  222.     int i;
  223.     /* Unlink object */
  224.     vlc_object_detach( p_sout );
  225.  
  226.     /* *** free all string *** */
  227.     FREE( p_sout->psz_sout );
  228.  
  229.     for( i = 0; i < p_sout->i_nb_dest; i++ )
  230.     {
  231.         FREE( p_sout->ppsz_dest[i] );
  232.     }
  233.     FREE( p_sout->ppsz_dest );
  234.  
  235.     /* *** there shouldn't be any input ** */
  236.     if( p_sout->i_nb_inputs > 0 )
  237.     {
  238.         msg_Err( p_sout, "i_nb_inputs=%d > 0 !!!!!!", p_sout->i_nb_inputs );
  239.         msg_Err( p_sout, "mmmh I have a bad feeling..." );
  240.     }
  241.     vlc_mutex_destroy( &p_sout->lock );
  242.  
  243.     /* *** remove all muxer *** */
  244.     for( i = 0; i < p_sout->i_nb_mux; i++ )
  245.     {
  246.         sout_access_out_t *p_access;
  247. #define p_mux p_sout->pp_mux[i]
  248.  
  249.         p_access = p_mux->p_access;
  250.  
  251.         MuxDelete( p_mux );
  252.         sout_AccessOutDelete( p_access );
  253. #undef  p_mux
  254.     }
  255.     FREE( p_sout->pp_mux );
  256.  
  257. #if 0
  258.     for( i = 0; i < p_sout->p_sys->i_nb_mux; i++ )
  259.     {
  260.         FREE( p_sout->p_sys->pp_mux[i] );
  261.     }
  262.     FREE( p_sout->p_sys->pp_mux );
  263. #endif
  264.  
  265.     /* Free structure */
  266.     vlc_object_destroy( p_sout );
  267. }
  268.  
  269.  
  270.  
  271. /*****************************************************************************
  272.  * InitInstance: opens appropriate modules
  273.  *****************************************************************************/
  274. static int      InstanceNewOutput   (sout_instance_t *p_sout, char *psz_dest )
  275. {
  276.     mrl_t   mrl;
  277.     char * psz_dup;
  278. #if 0
  279.     /* Parse dest string. Syntax : [[<access>][/<mux>]:][<dest>] */
  280.     /* This code is identical to input.c:InitThread. FIXME : factorize it ? */
  281.  
  282.     char * psz_dup = strdup( psz_dest );
  283.     char * psz_parser = psz_dup;
  284.     char * psz_access = "";
  285.     char * psz_mux = "";
  286.     char * psz_name = "";
  287.     /* *** first parse psz_dest */
  288.     while( *psz_parser && *psz_parser != ':' )
  289.     {
  290.         psz_parser++;
  291.     }
  292. #if defined( WIN32 ) || defined( UNDER_CE )
  293.     if( psz_parser - psz_dup == 1 )
  294.     {
  295.         msg_Warn( p_sout, "drive letter %c: found in source string",
  296.                           *psz_dup ) ;
  297.         psz_parser = "";
  298.     }
  299. #endif
  300.  
  301.     if( !*psz_parser )
  302.     {
  303.         psz_access = psz_mux = "";
  304.         psz_name = psz_dup;
  305.     }
  306.     else
  307.     {
  308.         *psz_parser++ = '\0';
  309.  
  310.         /* let's skip '//' */
  311.         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
  312.         {
  313.             psz_parser += 2 ;
  314.         }
  315.  
  316.         psz_name = psz_parser ;
  317.  
  318.         /* Come back to parse the access and mux plug-ins */
  319.         psz_parser = psz_dup;
  320.  
  321.         if( !*psz_parser )
  322.         {
  323.             /* No access */
  324.             psz_access = "";
  325.         }
  326.         else if( *psz_parser == '/' )
  327.         {
  328.             /* No access */
  329.             psz_access = "";
  330.             psz_parser++;
  331.         }
  332.         else
  333.         {
  334.             psz_access = psz_parser;
  335.  
  336.             while( *psz_parser && *psz_parser != '/' )
  337.             {
  338.                 psz_parser++;
  339.             }
  340.  
  341.             if( *psz_parser == '/' )
  342.             {
  343.                 *psz_parser++ = '\0';
  344.             }
  345.         }
  346.  
  347.         if( !*psz_parser )
  348.         {
  349.             /* No mux */
  350.             psz_mux = "";
  351.         }
  352.         else
  353.         {
  354.             psz_mux = psz_parser;
  355.         }
  356.     }
  357.  
  358.     msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
  359.              psz_access, psz_mux, psz_name );
  360. #endif
  361.  
  362.     mrl_Parse( &mrl, psz_dest );
  363.     msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
  364.              mrl.psz_access, mrl.psz_way, mrl.psz_name );
  365.  
  366.     vlc_mutex_lock( &p_sout->lock );
  367.     /* *** create mux *** */
  368.  
  369.     if( InstanceMuxNew( p_sout, mrl.psz_way, mrl.psz_access, mrl.psz_name ) )
  370.     {
  371.         msg_Err( p_sout, "cannot create sout chain for %s/%s://%s",
  372.                  mrl.psz_access, mrl.psz_way, mrl.psz_name );
  373.  
  374.         mrl_Clean( &mrl );
  375.         vlc_mutex_unlock( &p_sout->lock );
  376.         return( VLC_EGENERIC );
  377.     }
  378.     mrl_Clean( &mrl );
  379.  
  380.     /* *** finish all setup *** */
  381.     if( p_sout->psz_sout )
  382.     {
  383.         p_sout->psz_sout =
  384.             realloc( p_sout->psz_sout,
  385.                      strlen( p_sout->psz_sout ) +2+1+ strlen( psz_dest ) );
  386.         strcat( p_sout->psz_sout, "#" );
  387.         strcat( p_sout->psz_sout, psz_dest );
  388.     }
  389.     else
  390.     {
  391.         p_sout->psz_sout = strdup( psz_dest );
  392.     }
  393.     psz_dup = strdup( psz_dest );
  394.     TAB_APPEND( p_sout->i_nb_dest, p_sout->ppsz_dest, psz_dup );
  395.     vlc_mutex_unlock( &p_sout->lock );
  396.  
  397.     msg_Dbg( p_sout, "complete sout `%s'", p_sout->psz_sout );
  398.  
  399.     return VLC_SUCCESS;
  400. }
  401.  
  402. static int      InstanceMuxNew      ( sout_instance_t *p_sout,
  403.                                       char *psz_mux, char *psz_access, char *psz_name )
  404. {
  405.     sout_access_out_t *p_access;
  406.     sout_mux_t        *p_mux;
  407.  
  408.     /* *** find and open appropriate access module *** */
  409.     p_access =
  410.         sout_AccessOutNew( p_sout, psz_access, psz_name );
  411.     if( p_access == NULL )
  412.     {
  413.         msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
  414.                  psz_access, psz_mux, psz_name );
  415.         return( VLC_EGENERIC );
  416.     }
  417.  
  418.     /* *** find and open appropriate mux module *** */
  419.     p_mux = MuxNew( p_sout, psz_mux, p_access );
  420.     if( p_mux == NULL )
  421.     {
  422.         msg_Err( p_sout, "no suitable sout mux module for `%s/%s://%s'",
  423.                  psz_access, psz_mux, psz_name );
  424.  
  425.         sout_AccessOutDelete( p_access );
  426.         return( VLC_EGENERIC );
  427.     }
  428.  
  429.     p_sout->i_preheader = __MAX( p_sout->i_preheader,
  430.                                  p_mux->i_preheader );
  431.  
  432.     TAB_APPEND( p_sout->i_nb_mux, p_sout->pp_mux, p_mux );
  433.  
  434.  
  435.     return VLC_SUCCESS;
  436. }
  437. /*****************************************************************************
  438.  * sout_AccessOutNew: allocate a new access out
  439.  *****************************************************************************/
  440. sout_access_out_t *sout_AccessOutNew( sout_instance_t *p_sout,
  441.                                       char *psz_access, char *psz_name )
  442. {
  443.     sout_access_out_t *p_access;
  444.  
  445.     if( !( p_access = vlc_object_create( p_sout,
  446.                                          sizeof( sout_access_out_t ) ) ) )
  447.     {
  448.         msg_Err( p_sout, "out of memory" );
  449.         return NULL;
  450.     }
  451.     p_access->psz_access = strdup( psz_access ? psz_access : "" );
  452.     p_access->psz_name   = strdup( psz_name ? psz_name : "" );
  453.     p_access->p_sout     = p_sout;
  454.     p_access->p_sys = NULL;
  455.     p_access->pf_seek    = NULL;
  456.     p_access->pf_write   = NULL;
  457.  
  458.     p_access->p_module   = module_Need( p_access,
  459.                                         "sout access",
  460.                                         p_access->psz_access );;
  461.  
  462.     if( !p_access->p_module )
  463.     {
  464.         free( p_access->psz_access );
  465.         free( p_access->psz_name );
  466.         vlc_object_destroy( p_access );
  467.         return( NULL );
  468.     }
  469.  
  470.     return p_access;
  471. }
  472. /*****************************************************************************
  473.  * sout_AccessDelete: delete an access out
  474.  *****************************************************************************/
  475. void sout_AccessOutDelete( sout_access_out_t *p_access )
  476. {
  477.     if( p_access->p_module )
  478.     {
  479.         module_Unneed( p_access, p_access->p_module );
  480.     }
  481.     free( p_access->psz_access );
  482.     free( p_access->psz_name );
  483.  
  484.     vlc_object_destroy( p_access );
  485. }
  486.  
  487. /*****************************************************************************
  488.  * sout_AccessSeek:
  489.  *****************************************************************************/
  490. int  sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
  491. {
  492.     return( p_access->pf_seek( p_access, i_pos ) );
  493. }
  494.  
  495. /*****************************************************************************
  496.  * sout_AccessWrite:
  497.  *****************************************************************************/
  498. int  sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
  499. {
  500.     return( p_access->pf_write( p_access, p_buffer ) );
  501. }
  502.  
  503.  
  504.  
  505. static sout_input_t *SoutInputCreate( sout_instance_t *p_sout,
  506.                                       sout_packet_format_t *p_format )
  507. {
  508.     sout_input_t *p_input;
  509.  
  510.     p_input = malloc( sizeof( sout_input_t ) );
  511.  
  512.     p_input->p_sout = p_sout;
  513.     memcpy( &p_input->input_format,
  514.             p_format,
  515.             sizeof( sout_packet_format_t ) );
  516.     p_input->p_fifo = sout_FifoCreate( p_sout );
  517.     p_input->p_sys = NULL;
  518.  
  519.     return p_input;
  520. }
  521.  
  522. static void SoutInputDestroy( sout_instance_t *p_sout,
  523.                               sout_input_t *p_input )
  524. {
  525.     sout_FifoDestroy( p_sout, p_input->p_fifo );
  526.     free( p_input );
  527. }
  528.  
  529. /*****************************************************************************
  530.  * Mux*: create/destroy/manipulate muxer.
  531.  *  XXX: for now they are private, but I will near export them
  532.  *       to allow muxer creating private muxer (ogg in avi, flexmux in ts/ps)
  533.  *****************************************************************************/
  534.  
  535. /*****************************************************************************
  536.  * MuxNew: allocate a new mux
  537.  *****************************************************************************/
  538. static sout_mux_t * MuxNew              ( sout_instance_t *p_sout,
  539.                                           char *psz_mux,
  540.                                           sout_access_out_t *p_access )
  541. {
  542.     sout_mux_t *p_mux;
  543.  
  544.     p_mux = vlc_object_create( p_sout,
  545.                                sizeof( sout_mux_t ) );
  546.     if( p_mux == NULL )
  547.     {
  548.         msg_Err( p_sout, "out of memory" );
  549.         return NULL;
  550.     }
  551.  
  552.     p_mux->p_sout       = p_sout;
  553.     p_mux->psz_mux      = strdup( psz_mux);
  554.     p_mux->p_access     = p_access;
  555.     p_mux->i_preheader  = 0;
  556.     p_mux->pf_capacity  = NULL;
  557.     p_mux->pf_addstream = NULL;
  558.     p_mux->pf_delstream = NULL;
  559.     p_mux->pf_mux       = NULL;
  560.     p_mux->i_nb_inputs  = 0;
  561.     p_mux->pp_inputs    = NULL;
  562.  
  563.     p_mux->p_sys        = NULL;
  564.  
  565.     p_mux->p_module     = module_Need( p_mux,
  566.                                        "sout mux",
  567.                                        p_mux->psz_mux );
  568.     if( p_mux->p_module == NULL )
  569.     {
  570.         FREE( p_mux->psz_mux );
  571.  
  572.         vlc_object_destroy( p_mux );
  573.         return NULL;
  574.     }
  575.  
  576.     /* *** probe mux capacity *** */
  577.     if( p_mux->pf_capacity )
  578.     {
  579.         int b_answer;
  580.         if( p_mux->pf_capacity( p_mux,
  581.                                 SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME,
  582.                                 NULL, (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
  583.         {
  584.             b_answer = VLC_FALSE;
  585.         }
  586.         if( b_answer )
  587.         {
  588.             msg_Dbg( p_sout, "muxer support adding stream at any time" );
  589.             p_mux->b_add_stream_any_time = VLC_TRUE;
  590.             p_mux->b_waiting_stream = VLC_FALSE;
  591.         }
  592.         else
  593.         {
  594.             p_mux->b_add_stream_any_time = VLC_FALSE;
  595.             p_mux->b_waiting_stream = VLC_TRUE;
  596.         }
  597.     }
  598.     else
  599.     {
  600.         p_mux->b_add_stream_any_time = VLC_FALSE;
  601.         p_mux->b_waiting_stream = VLC_TRUE;
  602.     }
  603.     p_mux->i_add_stream_start = -1;
  604.  
  605.     return p_mux;
  606. }
  607.  
  608. static void MuxDelete               ( sout_mux_t *p_mux )
  609. {
  610.     if( p_mux->p_module )
  611.     {
  612.         module_Unneed( p_mux, p_mux->p_module );
  613.     }
  614.     free( p_mux->psz_mux );
  615.  
  616.     vlc_object_destroy( p_mux );
  617. }
  618.  
  619. static sout_input_t *MuxAddStream   ( sout_mux_t *p_mux,
  620.                                       sout_packet_format_t *p_format )
  621. {
  622.     sout_input_t *p_input;
  623.  
  624.     if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream)
  625.     {
  626.         msg_Err( p_mux, "cannot add a new stream (unsuported while muxing for this format)" );
  627.         return NULL;
  628.     }
  629.     if( p_mux->i_add_stream_start < 0 )
  630.     {
  631.         /* we wait for one second */
  632.         p_mux->i_add_stream_start = mdate();
  633.     }
  634.  
  635.     msg_Dbg( p_mux, "adding a new input" );
  636.     /* create a new sout input */
  637.     p_input = SoutInputCreate( p_mux->p_sout, p_format );
  638.  
  639.     TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
  640.     if( p_mux->pf_addstream( p_mux, p_input ) < 0 )
  641.     {
  642.             msg_Err( p_mux, "cannot add this stream" );
  643.             MuxDeleteStream( p_mux, p_input );
  644.             return( NULL );
  645.     }
  646.  
  647.     return( p_input );
  648. }
  649.  
  650. static void MuxDeleteStream     ( sout_mux_t *p_mux,
  651.                                   sout_input_t *p_input )
  652. {
  653.     int i_index;
  654.  
  655.     TAB_FIND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input, i_index );
  656.     if( i_index >= 0 )
  657.     {
  658.         if( p_mux->pf_delstream( p_mux, p_input ) < 0 )
  659.         {
  660.             msg_Err( p_mux, "cannot del this stream from mux" );
  661.         }
  662.  
  663.         /* remove the entry */
  664.         TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
  665.  
  666.         if( p_mux->i_nb_inputs == 0 )
  667.         {
  668.             msg_Warn( p_mux, "no more input stream for this mux" );
  669.         }
  670.  
  671.         SoutInputDestroy( p_mux->p_sout, p_input );
  672.     }
  673. }
  674.  
  675. static void MuxSendBuffer       ( sout_mux_t    *p_mux,
  676.                                   sout_input_t  *p_input,
  677.                                   sout_buffer_t *p_buffer )
  678. {
  679.     sout_FifoPut( p_input->p_fifo, p_buffer );
  680.  
  681.     if( p_mux->b_waiting_stream )
  682.     {
  683.         if( p_mux->i_add_stream_start > 0 &&
  684.             p_mux->i_add_stream_start + (mtime_t)1500000 < mdate() )
  685.         {
  686.             /* more than 1.5 second, start muxing */
  687.             p_mux->b_waiting_stream = VLC_FALSE;
  688.         }
  689.         else
  690.         {
  691.             return;
  692.         }
  693.     }
  694.     p_mux->pf_mux( p_mux );
  695. }
  696.  
  697. /*****************************************************************************
  698.  *
  699.  *****************************************************************************/
  700. sout_packetizer_input_t *__sout_InputNew( vlc_object_t *p_this,
  701.                                           sout_packet_format_t *p_format )
  702. {
  703.     sout_instance_t         *p_sout = NULL;
  704.     sout_packetizer_input_t *p_input;
  705.     int             i_try;
  706.     int             i_mux;
  707.     vlc_bool_t      b_accepted = VLC_FALSE;
  708.  
  709.     /* search an stream output */
  710.     for( i_try = 0; i_try < 12; i_try++ )
  711.     {
  712.         p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE );
  713.         if( !p_sout )
  714.         {
  715.             msleep( 100*1000 );
  716.             msg_Dbg( p_this, "waiting for sout" );
  717.         }
  718.         else
  719.         {
  720.             break;
  721.         }
  722.     }
  723.  
  724.     if( !p_sout )
  725.     {
  726.         msg_Err( p_this, "cannot find any stream ouput" );
  727.         return( NULL );
  728.     }
  729.     msg_Dbg( p_sout, "adding a new input" );
  730.  
  731.     /* *** create a packetizer input *** */
  732.     p_input = malloc( sizeof( sout_packetizer_input_t ) );
  733.     p_input->p_sout         = p_sout;
  734.     p_input->i_nb_inputs    = 0;
  735.     p_input->pp_inputs      = NULL;
  736.     p_input->i_nb_mux       = 0;
  737.     p_input->pp_mux         = NULL;
  738.     memcpy( &p_input->input_format,
  739.             p_format,
  740.             sizeof( sout_packet_format_t ) );
  741.  
  742.     if( p_format->i_fourcc == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
  743.     {
  744.         vlc_object_release( p_sout );
  745.         return p_input;
  746.     }
  747.  
  748.     vlc_mutex_lock( &p_sout->lock );
  749.     /* *** add this input to all muxers *** */
  750.     for( i_mux = 0; i_mux < p_sout->i_nb_mux; i_mux++ )
  751.     {
  752.         sout_input_t *p_mux_input;
  753. #define p_mux p_sout->pp_mux[i_mux]
  754.  
  755.         p_mux_input = MuxAddStream( p_mux, p_format );
  756.         if( p_mux_input )
  757.         {
  758.             TAB_APPEND( p_input->i_nb_inputs, p_input->pp_inputs, p_mux_input );
  759.             TAB_APPEND( p_input->i_nb_mux,    p_input->pp_mux,    p_mux );
  760.  
  761.             b_accepted = VLC_TRUE;
  762.         }
  763. #undef  p_mux
  764.     }
  765.  
  766.     if( !b_accepted )
  767.     {
  768.         /* all muxer refuse this stream, so delete it */
  769.         free( p_input );
  770.  
  771.         vlc_mutex_unlock( &p_sout->lock );
  772.         vlc_object_release( p_sout );
  773.         return( NULL );
  774.     }
  775.  
  776.     TAB_APPEND( p_sout->i_nb_inputs, p_sout->pp_inputs, p_input );
  777.     vlc_mutex_unlock( &p_sout->lock );
  778.  
  779.     vlc_object_release( p_sout );
  780.  
  781.     return( p_input );
  782. }
  783.  
  784.  
  785. int sout_InputDelete( sout_packetizer_input_t *p_input )
  786. {
  787.     sout_instance_t     *p_sout = p_input->p_sout;
  788.     int                 i_input;
  789.  
  790.     msg_Dbg( p_sout, "removing an input" );
  791.  
  792.     vlc_mutex_lock( &p_sout->lock );
  793.  
  794.     /* *** remove this input to all muxers *** */
  795.     for( i_input = 0; i_input < p_input->i_nb_inputs; i_input++ )
  796.     {
  797.         MuxDeleteStream( p_input->pp_mux[i_input], p_input->pp_inputs[i_input] );
  798.     }
  799.  
  800.     TAB_REMOVE( p_sout->i_nb_inputs, p_sout->pp_inputs, p_input );
  801.  
  802.     free( p_input->pp_inputs );
  803.     free( p_input->pp_mux );
  804.  
  805.     free( p_input );
  806.  
  807.     vlc_mutex_unlock( &p_sout->lock );
  808.     return( 0 );
  809. }
  810.  
  811.  
  812. int sout_InputSendBuffer( sout_packetizer_input_t *p_input, sout_buffer_t *p_buffer )
  813. {
  814. //    sout_instance_sys_t *p_sys = p_input->p_sout->p_sys;
  815. /*    msg_Dbg( p_input->p_sout,
  816.              "send buffer, size:%d", p_buffer->i_size ); */
  817.  
  818.     if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) &&
  819.         p_input->i_nb_inputs > 0 )
  820.     {
  821.         int i;
  822.  
  823.         vlc_mutex_lock( &p_input->p_sout->lock );
  824.         for( i = 0; i < p_input->i_nb_inputs - 1; i++ )
  825.         {
  826.             sout_buffer_t *p_dup;
  827.  
  828.             p_dup = sout_BufferDuplicate( p_input->p_sout, p_buffer );
  829.  
  830.             MuxSendBuffer( p_input->pp_mux[i],
  831.                            p_input->pp_inputs[i],
  832.                            p_dup );
  833.         }
  834.         MuxSendBuffer( p_input->pp_mux[p_input->i_nb_inputs-1],
  835.                        p_input->pp_inputs[p_input->i_nb_inputs-1],
  836.                        p_buffer );
  837.  
  838.         vlc_mutex_unlock( &p_input->p_sout->lock );
  839.     }
  840.     else
  841.     {
  842.         sout_BufferDelete( p_input->p_sout, p_buffer );
  843.     }
  844.     return( 0 );
  845. }
  846.  
  847. sout_fifo_t *sout_FifoCreate( sout_instance_t *p_sout )
  848. {
  849.     sout_fifo_t *p_fifo;
  850.  
  851.     if( !( p_fifo = malloc( sizeof( sout_fifo_t ) ) ) )
  852.     {
  853.         return( NULL );
  854.     }
  855.  
  856.     vlc_mutex_init( p_sout, &p_fifo->lock );
  857.     vlc_cond_init ( p_sout, &p_fifo->wait );
  858.     p_fifo->i_depth = 0;
  859.     p_fifo->p_first = NULL;
  860.     p_fifo->pp_last = &p_fifo->p_first;
  861.  
  862.     return( p_fifo );
  863. }
  864.  
  865. void       sout_FifoFree( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
  866. {
  867.     sout_buffer_t *p_buffer;
  868.  
  869.     vlc_mutex_lock( &p_fifo->lock );
  870.     p_buffer = p_fifo->p_first;
  871.     while( p_buffer )
  872.     {
  873.         sout_buffer_t *p_next;
  874.         p_next = p_buffer->p_next;
  875.         sout_BufferDelete( p_sout, p_buffer );
  876.         p_buffer = p_next;
  877.     }
  878.     vlc_mutex_unlock( &p_fifo->lock );
  879.  
  880.     return;
  881. }
  882. void       sout_FifoDestroy( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
  883. {
  884.     sout_FifoFree( p_sout, p_fifo );
  885.     vlc_mutex_destroy( &p_fifo->lock );
  886.     vlc_cond_destroy ( &p_fifo->wait );
  887.  
  888.     free( p_fifo );
  889. }
  890.  
  891. void        sout_FifoPut( sout_fifo_t *p_fifo, sout_buffer_t *p_buffer )
  892. {
  893.     vlc_mutex_lock( &p_fifo->lock );
  894.  
  895.     do
  896.     {
  897.         *p_fifo->pp_last = p_buffer;
  898.         p_fifo->pp_last = &p_buffer->p_next;
  899.         p_fifo->i_depth++;
  900.  
  901.         p_buffer = p_buffer->p_next;
  902.  
  903.     } while( p_buffer );
  904.  
  905.     /* warm there is data in this fifo */
  906.     vlc_cond_signal( &p_fifo->wait );
  907.     vlc_mutex_unlock( &p_fifo->lock );
  908. }
  909.  
  910. sout_buffer_t *sout_FifoGet( sout_fifo_t *p_fifo )
  911. {
  912.     sout_buffer_t *p_buffer;
  913.  
  914.     vlc_mutex_lock( &p_fifo->lock );
  915.  
  916.     if( p_fifo->p_first == NULL )
  917.     {
  918.         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
  919.     }
  920.  
  921.     p_buffer = p_fifo->p_first;
  922.  
  923.     p_fifo->p_first = p_buffer->p_next;
  924.     p_fifo->i_depth--;
  925.  
  926.     if( p_fifo->p_first == NULL )
  927.     {
  928.         p_fifo->pp_last = &p_fifo->p_first;
  929.     }
  930.  
  931.     vlc_mutex_unlock( &p_fifo->lock );
  932.  
  933.     p_buffer->p_next = NULL;
  934.     return( p_buffer );
  935. }
  936.  
  937. sout_buffer_t *sout_FifoShow( sout_fifo_t *p_fifo )
  938. {
  939.     sout_buffer_t *p_buffer;
  940.  
  941.     vlc_mutex_lock( &p_fifo->lock );
  942.  
  943.     if( p_fifo->p_first == NULL )
  944.     {
  945.         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
  946.     }
  947.  
  948.     p_buffer = p_fifo->p_first;
  949.  
  950.     vlc_mutex_unlock( &p_fifo->lock );
  951.  
  952.     return( p_buffer );
  953. }
  954.  
  955. sout_buffer_t *sout_BufferNew( sout_instance_t *p_sout, size_t i_size )
  956. {
  957.     sout_buffer_t *p_buffer;
  958.     size_t        i_preheader;
  959.  
  960. #ifdef DEBUG_BUFFER
  961.     msg_Dbg( p_sout, "allocating an new buffer, size:%d", (uint32_t)i_size );
  962. #endif
  963.  
  964.     p_buffer = malloc( sizeof( sout_buffer_t ) );
  965.     i_preheader = p_sout->i_preheader;
  966.  
  967.     if( i_size > 0 )
  968.     {
  969.         p_buffer->p_allocated_buffer = malloc( i_size + i_preheader );
  970.         p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
  971.     }
  972.     else
  973.     {
  974.         p_buffer->p_allocated_buffer = NULL;
  975.         p_buffer->p_buffer = NULL;
  976.     }
  977.     p_buffer->i_allocated_size = i_size + i_preheader;
  978.     p_buffer->i_buffer_size = i_size;
  979.  
  980.     p_buffer->i_size    = i_size;
  981.     p_buffer->i_length  = 0;
  982.     p_buffer->i_dts     = 0;
  983.     p_buffer->i_pts     = 0;
  984.     p_buffer->i_bitrate = 0;
  985.     p_buffer->i_flags   = 0x0000;
  986.     p_buffer->p_next = NULL;
  987.  
  988.     return( p_buffer );
  989. }
  990. int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t i_size )
  991. {
  992.     size_t          i_preheader;
  993.  
  994. #ifdef DEBUG_BUFFER
  995.     msg_Dbg( p_sout,
  996.              "realloc buffer old size:%d new size:%d",
  997.              (uint32_t)p_buffer->i_allocated_size,
  998.              (uint32_t)i_size );
  999. #endif
  1000.  
  1001.     i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
  1002.  
  1003.     if( !( p_buffer->p_allocated_buffer = realloc( p_buffer->p_allocated_buffer, i_size + i_preheader ) ) )
  1004.     {
  1005.         msg_Err( p_sout, "realloc failed" );
  1006.         p_buffer->i_allocated_size = 0;
  1007.         p_buffer->i_buffer_size = 0;
  1008.         p_buffer->i_size = 0;
  1009.         p_buffer->p_buffer = NULL;
  1010.         return( -1 );
  1011.     }
  1012.     p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
  1013.  
  1014.     p_buffer->i_allocated_size = i_size + i_preheader;
  1015.     p_buffer->i_buffer_size = i_size;
  1016.  
  1017.     return( 0 );
  1018. }
  1019.  
  1020. int sout_BufferReallocFromPreHeader( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t i_size )
  1021. {
  1022.     size_t  i_preheader;
  1023.  
  1024.     i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
  1025.  
  1026.     if( i_preheader < i_size )
  1027.     {
  1028.         return( -1 );
  1029.     }
  1030.  
  1031.     p_buffer->p_buffer -= i_size;
  1032.     p_buffer->i_size += i_size;
  1033.     p_buffer->i_buffer_size += i_size;
  1034.  
  1035.     return( 0 );
  1036. }
  1037.  
  1038. int sout_BufferDelete( sout_instance_t *p_sout, sout_buffer_t *p_buffer )
  1039. {
  1040. #ifdef DEBUG_BUFFER
  1041.     msg_Dbg( p_sout, "freeing buffer, size:%d", p_buffer->i_size );
  1042. #endif
  1043.     if( p_buffer->p_allocated_buffer )
  1044.     {
  1045.         free( p_buffer->p_allocated_buffer );
  1046.     }
  1047.     free( p_buffer );
  1048.     return( 0 );
  1049. }
  1050.  
  1051. sout_buffer_t *sout_BufferDuplicate( sout_instance_t *p_sout,
  1052.                                      sout_buffer_t *p_buffer )
  1053. {
  1054.     sout_buffer_t *p_dup;
  1055.  
  1056.     p_dup = sout_BufferNew( p_sout, p_buffer->i_size );
  1057.  
  1058.     p_dup->i_bitrate= p_buffer->i_bitrate;
  1059.     p_dup->i_dts    = p_buffer->i_dts;
  1060.     p_dup->i_pts    = p_buffer->i_pts;
  1061.     p_dup->i_length = p_buffer->i_length;
  1062.     p_dup->i_flags  = p_buffer->i_flags;
  1063.     p_sout->p_vlc->pf_memcpy( p_dup->p_buffer, p_buffer->p_buffer, p_buffer->i_size );
  1064.  
  1065.     return( p_dup );
  1066. }
  1067.  
  1068. void sout_BufferChain( sout_buffer_t **pp_chain,
  1069.                        sout_buffer_t *p_buffer )
  1070. {
  1071.     if( *pp_chain == NULL )
  1072.     {
  1073.         *pp_chain = p_buffer;
  1074.     }
  1075.     else if( p_buffer != NULL )
  1076.     {
  1077.         sout_buffer_t *p = *pp_chain;
  1078.  
  1079.         while( p->p_next )
  1080.         {
  1081.             p = p->p_next;
  1082.         }
  1083.  
  1084.         p->p_next = p_buffer;
  1085.     }
  1086. }
  1087.  
  1088. #if 0
  1089. static int mrl_ParseOptions( mrl_option_t **pp_opt, char *psz_options )
  1090. {
  1091.     mrl_option_t **pp_last = pp_opt;
  1092.  
  1093.     char *psz_parser = strdup( psz_options );
  1094.  
  1095.     *pp_last = NULL;
  1096.  
  1097.     if( *psz_parser == '=' )
  1098.     {
  1099.         free( psz_parser );
  1100.         return( VLC_EGENERIC );
  1101.     }
  1102.     if( *psz_parser == '{' )
  1103.     {
  1104.         free( psz_parser );
  1105.     }
  1106.  
  1107.     for( ;; )
  1108.     {
  1109.         char *psz_end;
  1110.         mrl_option_t opt;
  1111.  
  1112.         /* skip space */
  1113.         while( *psz_parser && ( *psz_parser == ' ' || *psz_parser == '\t' || *psz_parser == ';' ) )
  1114.         {
  1115.             psz_parser++;
  1116.         }
  1117.  
  1118.         if( ( psz_end = strchr( psz_parser, '=' ) ) != NULL )
  1119.         {
  1120.             opt.p_next = NULL;
  1121.  
  1122.             while( psz_end > psz_parser && ( *psz_end == ' ' ||  *psz_end == '\t' ) )
  1123.             {
  1124.                 psz_end--;
  1125.             }
  1126.  
  1127.             if( psz_end - psz_parser <= 0 )
  1128.             {
  1129.                 return( VLC_EGENERIC );
  1130.             }
  1131.  
  1132.             *psz_end = '\0';
  1133.             opt.psz_name = strdup( psz_parser );
  1134.  
  1135.             psz_parser = psz_end + 1;
  1136.             if( ( psz_end = strchr( psz_parser, ';' ) ) == NULL &&
  1137.                 ( psz_end = strchr( psz_parser, '}' ) ) == NULL )
  1138.             {
  1139.                 psz_end = psz_parser + strlen( psz_parser ) + 1;
  1140.             }
  1141.  
  1142.             opt.psz_value = strdup( psz_parser );
  1143.  
  1144.             fprintf( stderr, "option: name=`%s' value=`%s'\n",
  1145.                      opt.psz_name,
  1146.                      opt.psz_value );
  1147.             psz_parser = psz_end + 1;
  1148.  
  1149.             *pp_last = malloc( sizeof( mrl_option_t ) );
  1150.             **pp_last = opt;
  1151.         }
  1152.         else
  1153.         {
  1154.             break;
  1155.         }
  1156.     }
  1157. }
  1158. #endif
  1159.  
  1160. static int  mrl_Parse( mrl_t *p_mrl, char *psz_mrl )
  1161. {
  1162.     char * psz_dup = strdup( psz_mrl );
  1163.     char * psz_parser = psz_dup;
  1164.     char * psz_access = "";
  1165.     char * psz_way = "";
  1166.     char * psz_name = "";
  1167.  
  1168.     /* *** first parse psz_dest */
  1169.     while( *psz_parser && *psz_parser != ':' )
  1170.     {
  1171.         if( *psz_parser == '{' )
  1172.         {
  1173.             while( *psz_parser && *psz_parser != '}' )
  1174.             {
  1175.                 psz_parser++;
  1176.             }
  1177.             if( *psz_parser )
  1178.             {
  1179.                 psz_parser++;
  1180.             }
  1181.         }
  1182.         else
  1183.         {
  1184.             psz_parser++;
  1185.         }
  1186.     }
  1187. #if defined( WIN32 ) || defined( UNDER_CE )
  1188.     if( psz_parser - psz_dup == 1 )
  1189.     {
  1190.         /* msg_Warn( p_sout, "drive letter %c: found in source string",
  1191.                           *psz_dup ) ; */
  1192.         psz_parser = "";
  1193.     }
  1194. #endif
  1195.  
  1196.     if( !*psz_parser )
  1197.     {
  1198.         psz_access = psz_way = "";
  1199.         psz_name = psz_dup;
  1200.     }
  1201.     else
  1202.     {
  1203.         *psz_parser++ = '\0';
  1204.  
  1205.         /* let's skip '//' */
  1206.         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
  1207.         {
  1208.             psz_parser += 2 ;
  1209.         }
  1210.  
  1211.         psz_name = psz_parser ;
  1212.  
  1213.         /* Come back to parse the access and mux plug-ins */
  1214.         psz_parser = psz_dup;
  1215.  
  1216.         if( !*psz_parser )
  1217.         {
  1218.             /* No access */
  1219.             psz_access = "";
  1220.         }
  1221.         else if( *psz_parser == '/' )
  1222.         {
  1223.             /* No access */
  1224.             psz_access = "";
  1225.             psz_parser++;
  1226.         }
  1227.         else
  1228.         {
  1229.             psz_access = psz_parser;
  1230.  
  1231.             while( *psz_parser && *psz_parser != '/' )
  1232.             {
  1233.                 if( *psz_parser == '{' )
  1234.                 {
  1235.                     while( *psz_parser && *psz_parser != '}' )
  1236.                     {
  1237.                         psz_parser++;
  1238.                     }
  1239.                     if( *psz_parser )
  1240.                     {
  1241.                         psz_parser++;
  1242.                     }
  1243.                 }
  1244.                 else
  1245.                 {
  1246.                     psz_parser++;
  1247.                 }
  1248.             }
  1249.  
  1250.             if( *psz_parser == '/' )
  1251.             {
  1252.                 *psz_parser++ = '\0';
  1253.             }
  1254.         }
  1255.  
  1256.         if( !*psz_parser )
  1257.         {
  1258.             /* No mux */
  1259.             psz_way = "";
  1260.         }
  1261.         else
  1262.         {
  1263.             psz_way = psz_parser;
  1264.         }
  1265.     }
  1266.  
  1267. #if 0
  1268.     if( ( psz_parser = strchr( psz_access, '{' ) ) != NULL )
  1269.     {
  1270.         mrl_ParseOptions( &p_mrl->p_access_options, psz_parser );
  1271.         *psz_parser = '\0';
  1272.     }
  1273.  
  1274.     if( ( psz_parser = strchr( psz_way, '{' ) ) != NULL )
  1275.     {
  1276.         mrl_ParseOptions( &p_mrl->p_way_options, psz_parser );
  1277.         *psz_parser = '\0';
  1278.     }
  1279. #endif
  1280.  
  1281.     p_mrl->p_access_options = NULL;
  1282.     p_mrl->p_way_options    = NULL;
  1283.  
  1284.     p_mrl->psz_access = strdup( psz_access );
  1285.     p_mrl->psz_way    = strdup( psz_way );
  1286.     p_mrl->psz_name   = strdup( psz_name );
  1287.  
  1288.     free( psz_dup );
  1289.     return( VLC_SUCCESS );
  1290. }
  1291.  
  1292.  
  1293. /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
  1294. static void mrl_Clean( mrl_t *p_mrl )
  1295. {
  1296.     FREE( p_mrl->psz_access );
  1297.     FREE( p_mrl->psz_way );
  1298.     FREE( p_mrl->psz_name );
  1299. }
  1300.  
  1301.  
  1302.  
  1303.